﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.IO;

namespace OpenGL
{
	//In this version texture coordinates applies orthogonal system
	//Upper Left corner (X=0;Y=0) is TexCoord(0,0)
	public class GLTexture
	{
		uint[] TXTID;
		Bitmap Data;

		public GLTexture()
		{
			TXTID = null;
		}

		void LoadFile(String FN)
		{
			MemoryStream MS = new MemoryStream();
			byte[] Buf = File.ReadAllBytes(FN);
			MS.Write(Buf, 0, Buf.Length);
			Data = (Bitmap)Image.FromStream(MS);
			MS.Close();
			MS.Dispose();
			Generate();
		}
		String filename;
		public GLTexture(String FileName)
		{
			filename = FileName;
			Reload();
			return;
		}
		public void Reload()
		{
			LoadFile(filename);
		}
		public GLTexture(Bitmap data)
		{
			Data = data;
			Generate();
		}
		public void Generate()
		{
			TXTID = new uint[1] { 0 };
			GL.glGenTextures(1, TXTID);

			BitmapData bitmapData = Data.LockBits(new Rectangle(0, 0, Data.Width, Data.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

			//	Set the width and height.
			int width = Data.Width;
			int height = Data.Height;

			//	Bind our texture object (make it the current texture).
			GL.glBindTexture(GL.GL_TEXTURE_2D, TXTID[0]);

			//  Set the image data.
			GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA,
				width, height, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE,
				bitmapData.Scan0);

			//  Unlock the image.
			Data.UnlockBits(bitmapData);

			//  Dispose of the image file.
			//I.Dispose();

			//  Set linear filtering mode.
			GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR);
			GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR);
		}

		public void Bind()
		{
			//	Bind our texture object (make it the current texture).
			GL.glBindTexture(GL.GL_TEXTURE_2D, TXTID[0]);
		}

		public void Draw(double Width, double Height, double Multiply, int Tiles)
		{
			GL.glPushAttrib(GL.GL_ALL_ATTRIB_BITS);
			for (int N = 0; N < 1; N++)
			{
				if (N == 0)
				{
					GL.glEnable(GL.GL_TEXTURE_2D);
					Bind();
				}
				else
				{
					GL.glDisable(GL.GL_TEXTURE_2D);
					GL.glDisable(GL.GL_LIGHTING);
					GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE);
					GL.glCol3D(V3D.Green);
					GL.glLineWidth(3);
					GL.glDisable(GL.GL_DEPTH_TEST);
				}
				GL.glBegin(GL.GL_QUADS);
				GL.glNorm3D(V3D.Blue);
				for (double i = 0; i < Tiles; i++)
					for (double j = 0; j < Tiles; j++)
					{
						double s1 = Algebra3D.Map(0, Tiles, i, 0, 1);
						double s2 = Algebra3D.Map(0, Tiles, i + 1, 0, 1);
						double t1 = Algebra3D.Map(0, Tiles, j, 1, 0);
						double t2 = Algebra3D.Map(0, Tiles, j + 1, 1, 0);

						double x1 = Algebra3D.Map(0, Tiles, i, -Width / 2, Width / 2);
						double x2 = Algebra3D.Map(0, Tiles, i + 1, -Width / 2, Width / 2);

						double y1 = Algebra3D.Map(0, Tiles, j, -Height / 2, Height / 2);
						double y2 = Algebra3D.Map(0, Tiles, j + 1, -Height / 2, Height / 2);

						GL.glTexCoord2d(s1, t1);
						GL.glVertex3d(x1, y1, 0);
						GL.glTexCoord2d(s1, t2);
						GL.glVertex3d(x1, y2, 0);
						GL.glTexCoord2d(s2, t2);
						GL.glVertex3d(x2, y2, 0);
						GL.glTexCoord2d(s2, t1);
						GL.glVertex3d(x2, y1, 0);
					}
				GL.glEnd();
			}
			GL.glPopAttrib();
		}
	}
}